package org.xxpay.pay.channel.xinfu;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.xxpay.common.bean.result.PayException;
import org.xxpay.common.exception.PayErrorException;
import org.xxpay.common.util.DateUtils;
import org.xxpay.common.util.HtmlUtils;
import org.xxpay.common.util.XML;
import org.xxpay.common.util.sign.SignUtils;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayment;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static org.xxpay.common.util.XML.newDocument;

@Component
public class XinfuPaymentService extends BasePayment {
    private final static String logPrefix = "【信付支付】";

    // 下单查询串
    private final static String ORDER_CREATE_STR = "/Pay_Index.html";
    // 订单查询请求串
    private final static String ORDER_QUERY_STR = "/pay?tranType=payment&param=";
    @Override
    public String getChannelName() {
        return XinfuConfig.CHANNEL_NAME;
    }
    /**
     * 支付下单
     * @param payOrder
     * @return
     */
    @Override
    public JSONObject pay(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        JSONObject retObj;
        switch (channelId) {
            case XinfuConfig.CHANMEL_NAME_QUICK:
                retObj = doOrderReq(payOrder);
                break;
            default:
                retObj = buildRetObj(PayConstant.RETURN_VALUE_FAIL, "不支持的渠道[channelId="+channelId+"]");
                break;
        }
        return retObj;
    }

    /**
     * 查询订单
     * @param payOrder
     * @return
     */
    @Override
    public JSONObject query(PayOrder payOrder) {
        XinfuConfig config = new XinfuConfig(getPayParam(payOrder));
        Map<String,Object> params = new HashMap<>();
        params.put("tranName","queryOrder");
        params.put("version", "1.00");

        params.put("orderNo", payOrder.getPayOrderId());
        params.put("merCode", config.getMchId());
        params.put("orderType", "payment");
        params.put("sign", getSign(params,config.getPrivateKey()));
        _log.info("{}请求数据:{}", getChannelName(), JSON.toJSONString(params));
        String par = XML.getMap2Xml(params);
        // 响应对象
     return null;
    }
    //下单具体实现
    private JSONObject doOrderReq(PayOrder payOrder){
        XinfuConfig config = new XinfuConfig(getPayParam(payOrder));
        Map<String,Object> params = new HashMap<>();
        params.put("tranName","payment");
        params.put("version", "1.00");
        params.put("merCode", config.getMchId());
        params.put("orderNo", payOrder.getPayOrderId());
        params.put("orderTime", DateUtils.YYYYMMDDHHMMSS.format(new Date()));
        params.put("payType","11");
        params.put("amount", payOrder.getAmount());//单位 分
        params.put("currency", "CNY");
        params.put("productName", "网上充值");
        params.put("notifyURL", payConfig.getNotifyUrl(getChannelName()));
        params.put("sign", getSign(params,config.getPrivateKey()));
        _log.info("{}请求数据:{}", getChannelName(), JSON.toJSONString(params));
        String par = getMap2Xml(params);
        try {
            par = URLEncoder.encode( par, "UTF-8" );
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        _log.info("{}请求数据XML:{}", getChannelName(), par);
        //将订单改为支付中
        rpcCommonService.rpcPayOrderService.updateStatus4Ing(payOrder.getPayOrderId(), null);
        // 响应对象
        JSONObject retObj = new JSONObject();
        String payUrl = getReqUrl(config.getRequestUrl(),ORDER_QUERY_STR);
        payUrl = payUrl + par;
//        Map<String,Object> reqPrameters = new HashMap<>();
//        reqPrameters.put("tranType","payment");
//        reqPrameters.put("param",par);
//        String payForm = HtmlUtils.form(payUrl, HtmlUtils.POST, reqPrameters);
        return buildPayResultOfForm(retObj, payOrder,form(payUrl, HtmlUtils.POST) );
    }

    //获取sign
    private String getSign(Map<String,Object> params,String key){
        String signTxt = SignUtils.parameterText(params);
        _log.info("{}待签名字符串：{}", logPrefix, signTxt+"&key="+key);
        String sign = SignUtils.MD5.createSign(signTxt, "&key="+key, SignUtils.CHARSET_UTF8);
        return sign;
    }

    /**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     */
    public static String getMap2Xml(Map<String, Object> data) {


        Document document = null;
        try {
            document = newDocument();
        } catch (ParserConfigurationException e) {
            throw new PayErrorException(new PayException("ParserConfigurationException", e.getLocalizedMessage()));
        }
        org.w3c.dom.Element root = document.createElement("payment");
        document.appendChild(root);
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            Object value = entry.getValue();
            if (value == null) {
                value = "";
            }
            value = value.toString().trim();
            org.w3c.dom.Element filed = document.createElement(entry.getKey());
            filed.appendChild(document.createTextNode(value.toString()));
            root.appendChild(filed);
        }
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            DOMSource source = new DOMSource(document);
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StringWriter writer = new StringWriter();
            StreamResult result = new StreamResult(writer);
            transformer.transform(source, result);
            String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
            return output;
        } catch (TransformerException e) {
            e.printStackTrace();
        }


        return "";
    }

    public static String form(String url, String method) {
        StringBuilder form = new StringBuilder();
        form.append("<form id='form_submit' name='form_submit' action='"+url+"' method='"+method+"'>");
        form.append("   <input type='submit' value='POST' style='display:none;'>");
        form.append("</form>");
        form.append("<script>");
        form.append("        document.forms['form_submit'].submit();");
        form.append("</script>");
        return form.toString();
    }

}
